package com.empress.uranus.zma.biz.machine.impl;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.empress.uranus.zma.biz.machine.HeartbeatServerHandlerBiz;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;

/**
 * 服务器心跳机制
 * 
 * @author taoxuejun
 * @created 2017/7/18
 */
@ChannelHandler.Sharable
@Service("heartbeatServerHandlerBiz")
public class HeartbeatServerHandlerBizImpl extends HeartbeatServerHandlerBiz{

private final static Logger LOGGER = LoggerFactory.getLogger(HeartbeatServerHandlerBizImpl.class);
	
	private static final ByteBuf HEARTBEAT_SEQUENCE = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Heartbeat", CharsetUtil.UTF_8));
	 
	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
	 
		if (evt instanceof IdleStateEvent) {
			IdleStateEvent event = (IdleStateEvent) evt;
			String type = "";
			if (event.state() == IdleState.READER_IDLE) {
				type = "read idle";
			} else if (event.state() == IdleState.WRITER_IDLE) {
				type = "write idle";
			} else if (event.state() == IdleState.ALL_IDLE) {
				type = "read and write idle";
			}
			//发送的心跳并添加一个侦听器，如果发送操作失败将关闭连接
			ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
	  
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			LOGGER.info("the heart beat server handler has been invoked at " 
					+ formatter.format(new Date()) +" for client_ip:"+ ctx.channel().remoteAddress()+";超时类型:" + type);
		} else {
	         super.userEventTriggered(ctx, evt);
		}
	}	 
	
	@Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}
